from decimal import Decimal
from time import sleep

from django.db import transaction
from django.http import JsonResponse
# Create your views here.
from django.utils import timezone
from django.views import View
from django_redis import get_redis_connection

from apps.goods.models import SKU
from apps.orders.models import OrderInfo, OrderGoods
from apps.users.models import Address
from utils.transformJson import TransformJson
from utils.views import LoginRequiredJSONMixin


class OrderSettlementView(View):
    def get(self, request):
        user = request.user

        # 查询当前用户的所有地址信息
        addresses = Address.objects.filter(user=request.user,
                                           is_deleted=False)

        # 从Redis购物车中查询出被勾选的商品信息
        redis_cli = get_redis_connection('carts')
        pipeline = redis_cli.pipeline()
        pipeline.hgetall('carts_%s' % user.id)
        pipeline.smembers('selected_%s' % user.id)
        result = pipeline.execute()
        # redis_cart = redis_conn.hgetall('carts_%s' % user.id)
        # cart_selected = redis_conn.smembers('selected_%s' % user.id)
        redis_cart = result[0]
        cart_selected = result[1]
        cart = {}
        # 组织新的数据（只需要选中商品的信息）
        for sku_id in cart_selected:
            cart[int(sku_id)] = int(redis_cart[sku_id])

        # 查询商品信息
        sku_list = []
        # 查询商品信息
        skus = SKU.objects.filter(id__in=cart.keys())
        for sku in skus:
            sku_list.append({
                'id': sku.id,
                'name': sku.name,
                'default_image_url': sku.default_image.url,
                'count': cart[sku.id],
                'price': sku.price
            })

        addresses_list = []
        for address in addresses:
            addresses_list.append({
                'id': address.id,
                'province': address.province.name,
                'city': address.city.name,
                'district': address.district.name,
                'place': address.place,
                'receiver': address.receiver,
                'mobile': address.mobile
            })

        # 运费波动，单独设置
        freight = Decimal('10.00')

        # 渲染界面
        context = {
            'addresses': addresses_list,
            'skus': sku_list,
            'freight': freight,
            'defAddress': user.default_address_id,
        }

        return JsonResponse({'code': 0,
                             'errmsg': 'ok',
                             'context': context})


class OrderCommitView(LoginRequiredJSONMixin, View):
    # 保存订单商品信息
    def post(self, request):
        user = request.user
        data = TransformJson(request)
        address_id = data.get('address_id')
        pay_method = data.get('pay_method')
        # 验证数据
        if not all([address_id, pay_method]):
            return JsonResponse({'code': 400, 'errmsg': '参数不全'})
        try:
            address = Address.objects.get(id=address_id)
        except Address.DoesNotExist:
            return JsonResponse({'code': 400, 'errmsg': '参数不正确'})
        # 1为货到，2为支付宝
        if pay_method not in [1, 2]:
            return JsonResponse({'code': 400, 'errmsg': '参数不正确'})
        # 生成订单id 年月日+时分秒+9位用户Id
        order_id = timezone.localtime().strftime("%Y%m%d%H%M%S") + '%09d' % user.id
        if pay_method == OrderInfo.PAY_METHODS_ENUM['CASH']:
            status = OrderInfo.ORDER_STATUS_ENUM['UNSEND']  # 待发货
        else:
            status = OrderInfo.ORDER_STATUS_ENUM['UNPAID']  # 待支付
        total_count = 0
        total_amount = Decimal('0')
        freight = Decimal('10.00')
        with transaction.atomic():
            # 事务开始点
            point = transaction.savepoint()
            orderinfo = OrderInfo.objects.create(
                order_id=order_id,
                user_id=user.id,
                address=address,
                total_amount=total_amount,
                total_count=total_count,
                freight=freight,
                status=status,
                pay_method=pay_method,
            )
            # 保存订单商品信息
            redis_cli = get_redis_connection('carts')
            # 获取全部商品信息
            sku_id_counts = redis_cli.hgetall('carts_%s' % user.id)
            # 判断选中状态
            selected_ids = redis_cli.smembers('selected_%s' % user.id)
            carts = {}
            # 进行遍历赋值
            for sku_id in selected_ids:
                carts[int(sku_id)] = int(sku_id_counts[sku_id])
            for sku_id, count in carts.items():
                for i in range(3, 10):
                    # 根据商品id进行查询
                    sku = SKU.objects.get(id=sku_id)
                    # 判断商品库存
                    if sku.stock < count:
                        # 回滚点
                        transaction.savepoint_rollback(point)
                        return JsonResponse({'code': 400, 'errmsg': '库存不足~~'})
                    # 修改sku表数据,使用乐观锁防止超量售卖
                    # 1. 获取更新前数据
                    old_stock = sku.stock
                    # 2. 设置一个新数据，更新数据时使用
                    new_stock = sku.stock - count
                    new_sales = sku.sales + count
                    result = SKU.objects.filter(id=sku_id, stock=old_stock).update(stock=new_stock, sales=new_sales)
                    if result == 0:
                        sleep(7)
                        i += 1
                        continue
                    # 修改订单信息表数据
                    orderinfo.total_count += count
                    orderinfo.total_amount += (count * sku.price)
                    OrderGoods.objects.create(
                        order=orderinfo,
                        sku=sku,
                        count=count,
                        price=sku.price, )
                    break
            orderinfo.save()
            # 清除购物车中信息
            pl = redis_cli.pipeline()
            pl.hdel('carts_%s' % user.id, *selected_ids)
            pl.srem('selected_%s' % user.id, *selected_ids)
            pl.execute()
            # 事务提交点
            transaction.savepoint_commit(point)
        return JsonResponse({'code': 0, ' errmsg': 'ok', 'order_id': order_id})
